/*
  Copyright (C) 2011 Zhao Ming(zhao.ming29@gmail.com)

  All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License version 2.1, as
  published by the Free Software Foundation.  This program is
  distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "Rcosfir.h"
#include "DownInterp.h"
#include "AWGN.h"
#include "carrier.h"
#include "LogFile.h"

#include <LRCTransmiter.h>
#include <LRCReceiver.h>
#include <GHGS.h>

#include <math.h>
#include <stdio.h>
struct Message Rmessage[MAXMES];

int D[] = {64,   4,   8,   2,  16,   1,  32};
int W[] = {-1,  -1,  -1,   1,   1,   1,   1};

int main( int argc, char *argv[] )
{
	const double ChipRate = 27./12.*1e6;
	const double SampleRate = ChipRate * 4;
	const double ReceiverSampleRate = SampleRate/2.*(1+50.e-6);
	const double CarrierOffset = 27e6*(50.e-6);
	const int NCOWIDTH = 24;
	const int Amplitude = 32;
	const int frameLen = 128+640*2;
	const int simLen = 4500000;
	
	char *tbuf = new char[frameLen/8];
	char *rbuf = new char[frameLen*4];
	int bitCounter = 0;
	int chipCounter =0;
	int recvCounter =0;
	double ebn0;
	sscanf( argv[1],"%lf",&ebn0 );
	int TH;
	sscanf( argv[2],"%d",&TH );
	
	CAWGN *channel = new CAWGN( 4., 10./512., 1/128., ebn0 );
	CRcosfir *Tfir = new CRcosfir();
	CRcosfir *RfirI = new CRcosfir();
	CRcosfir *RfirQ = new CRcosfir();
	
	double rate=1.-ReceiverSampleRate/SampleRate;
	int nco=(1<<NCOWIDTH);
	rate*=(double)nco;
	CDownInterp *Down = new CDownInterp( (int)rate, NCOWIDTH, 8 );
	rate = CarrierOffset*(double)nco/SampleRate;
	
	CCarrier *freqOff = new CCarrier( (int)rate, NCOWIDTH );
	CLRCTransmiter *aT = new CLRCTransmiter(1,1,2);
	CLRCReceiver *aR = new CLRCReceiver( 1,1,2,TH );

	LogFile *log = new LogFile();
	log->setrec( 1, "work/RecvData.log" );
	GHGS *ghgsI[2],*ghgsQ[2];
	
	ghgsI[0] = new GHGS(7,D,W);
	ghgsQ[0] = new GHGS(7,D,W);
	ghgsI[1] = new GHGS(7,D,W);
	ghgsQ[1] = new GHGS(7,D,W);
	
	int i,j,k;
	int message = 0;
	int mes[2] = { message&0x3ff, message>>10 };
	aT->send(tbuf,	mes, 2);
	int tfir,tr,ti,rr,ri,rfirr,rfiri,dr,di;
	for( i=0;i<simLen;i++ )
	{
		chipCounter++;
		if( chipCounter==4 )
		{
			chipCounter=0;
			int c = tbuf[bitCounter/8]>>(bitCounter%8);
			c&=1;
			c=Amplitude*(1-2*c);
			Tfir->cei( c, tfir );
			bitCounter++;
			if( bitCounter == frameLen )
			{
				bitCounter=0;	
				message++;
				mes[0] = message&0x3ff;
				mes[1] = message>>10;
				aT->send(tbuf,	mes, 2);
			}	
		}
		else
			Tfir->cei( 0, tfir );
		freqOff->cei(tfir, 0, tr, ti);
		channel->cei( tr, ti, rr, ri );
		RfirI->cei( rr, rfirr );
		RfirQ->cei( ri, rfiri );
		if( Down->cei( rfirr,rfiri, dr, di )==1 )
		{
			rbuf[recvCounter*2]=(char)dr;
			rbuf[recvCounter*2+1]=(char)di;
			int pr,pi,T;
			
			ghgsI[recvCounter&1]->doit( dr,pr,T );
			ghgsQ[recvCounter&1]->doit( di,pi,T );
			
			log->rec( pr, pi, 1 );
			log->recflag = 0;
			recvCounter++;
			if( recvCounter==2*512 )
			{
				recvCounter = 0;
				int num = aR->recv( rbuf, 512*4, Rmessage );
				for( j=0;j<num;j++ )
				{
					for( k=0;k<Rmessage[j].len;k++ )
						printf("%d ",Rmessage[j].mes[k]);
					printf("\n");	
				}
				
			} 
		}	
	}
	delete tbuf;
	delete rbuf;
	delete channel;
	delete Tfir;
	delete RfirI;
	delete RfirQ;
	delete Down;
	delete freqOff;
	delete aT;
	delete aR;
	delete log;
	return 0;
}
